package cn.xo68.boot.job;

import cn.xo68.boot.job.common.QuartzContants;
import cn.xo68.boot.job.entity.JobType;
import cn.xo68.boot.job.entity.QuartzJob;
import cn.xo68.core.util.JsonUtil;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 调度任务操作服务
 * @author  wuxie
 * @date 2018-6-22
 */
public class JobOperateService {

    private static  final Logger logger=LoggerFactory.getLogger(JobOperateService.class);

    private final Scheduler scheduler;
    private final JsonUtil jsonUtil;

    public JobOperateService(Scheduler scheduler, JsonUtil jsonUtil) {
        this.scheduler = scheduler;
        this.jsonUtil = jsonUtil;
    }

    public Boolean add(QuartzJob quartzJob){
       return add(quartzJob, true);
    }
    public Boolean add(QuartzJob quartzJob, boolean restart){
        Boolean result=true;
        TriggerKey triggerKey = TriggerKey.triggerKey(quartzJob.getJobName(), quartzJob.getJobGroup());
        // 获取trigger，即在spring配置文件中定义的 bean id="myTrigger"
        try {
            Trigger trigger = scheduler.getTrigger(triggerKey);
            if (trigger == null) {
                JobDetail jobDetail = JobBuilder.newJob(JobExecutor.class)
                        .withIdentity(quartzJob.getJobName(), quartzJob.getJobGroup())
                        //.usingJobData("jobName", quartzJob.getJobName())
                        .withDescription(quartzJob.getDescription()).build();
                jobDetail.getJobDataMap().put(QuartzContants.DATAMAP_JOB_ID, quartzJob.getJobId());
                jobDetail.getJobDataMap().put(QuartzContants.DATAMAP_SCHED_NAME, quartzJob.getScheduleName());
                jobDetail.getJobDataMap().put(QuartzContants.DATAMAP_JOB_NAME, quartzJob.getJobName());
                jobDetail.getJobDataMap().put(QuartzContants.DATAMAP_JOB_GROUP, quartzJob.getJobGroup());
                jobDetail.getJobDataMap().put(QuartzContants.DATAMAP_JOB_ENTITY, jsonUtil.toString(quartzJob));



                // 按新的cronExpression表达式构建一个新的trigger
                TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger().withIdentity(quartzJob.getJobName(), quartzJob.getJobGroup());
                        //.startAt(quartzJob.getStartTime());
                        //.endAt(quartzJob.getEndTime())
                        //.withSchedule(scheduleBuilder).build();
                //trigger=triggerBuilder.build();
                if(quartzJob.getStartTime()!=null){
                    triggerBuilder.startAt(quartzJob.getStartTime());
                }else {
                    triggerBuilder.startNow();
                }
                if(quartzJob.getEndTime()!=null){
                    triggerBuilder.endAt(quartzJob.getEndTime());
                }
                if(quartzJob.getJobType()== JobType.CronSchedule.getCode()){
                    // 表达式调度构建器
                    CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzJob.getCronExpression());
                    trigger =triggerBuilder.withSchedule(scheduleBuilder).build();
                }else {
                    SimpleScheduleBuilder simpleScheduleBuilder=null;
                    if(quartzJob.getRepeatCount()<=0){
                        simpleScheduleBuilder=SimpleScheduleBuilder.repeatSecondlyForever(quartzJob.getIntervalInSeconds());
                    }else {
                        simpleScheduleBuilder=SimpleScheduleBuilder.repeatSecondlyForTotalCount(quartzJob.getRepeatCount(),quartzJob.getIntervalInSeconds());
                    }
                    trigger =triggerBuilder.withSchedule(simpleScheduleBuilder).build();
                }
                trigger.getJobDataMap().put(QuartzContants.DATAMAP_JOB_ID, quartzJob.getJobId());

                scheduler.scheduleJob(jobDetail, trigger);
            }else if(restart) {
                // Trigger已存在，那么更新相应的定时设置
                if(quartzJob.getJobType()== JobType.CronSchedule.getCode()){
                     // 表达式调度构建器
                    CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzJob.getCronExpression());

                    // 按新的cronExpression表达式重新构建trigger
                    trigger = ((CronTrigger)trigger).getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
                }else {
                    SimpleScheduleBuilder simpleScheduleBuilder=null;
                    if(quartzJob.getRepeatCount()<=0){
                        simpleScheduleBuilder=SimpleScheduleBuilder.repeatSecondlyForever(quartzJob.getIntervalInSeconds());
                    }else {
                        simpleScheduleBuilder=SimpleScheduleBuilder.repeatSecondlyForTotalCount(quartzJob.getRepeatCount(),quartzJob.getIntervalInSeconds());
                    }
                    // 按新的cronExpression表达式重新构建trigger
                    trigger = ((SimpleTrigger)trigger).getTriggerBuilder().withIdentity(triggerKey).withSchedule(simpleScheduleBuilder).build();
                }
                trigger.getJobDataMap().put(QuartzContants.DATAMAP_JOB_ID, quartzJob.getJobId());

                // 按新的trigger重新设置job执行
                scheduler.rescheduleJob(triggerKey, trigger);
            }

        } catch (SchedulerException e) {
            logger.error("添加调度任务异常", e);
            result=false;
        }
        return result;
    }

    /**
     * 触发
     * @param quartzJob
     * @return
     */
    public  Boolean trigger(QuartzJob quartzJob) {
        Boolean result=true;
        try {
            JobKey key = new JobKey(quartzJob.getJobName(),quartzJob.getJobGroup());
            scheduler.triggerJob(key);
        } catch (SchedulerException e) {
            logger.error("触发调度任务异常", e);
            result=false;
        }
        return result;
    }

    /**
     * 暂停
     * @param quartzJob
     * @return
     */
    public  Boolean pause(QuartzJob quartzJob) {
        Boolean result=true;
        try {
            JobKey key = new JobKey(quartzJob.getJobName(),quartzJob.getJobGroup());
            scheduler.pauseJob(key);
        } catch (SchedulerException e) {
            logger.error("暂停调度任务异常", e);
            result=false;
        }
        return result;
    }

    /**
     * 恢复
     * @param quartzJob
     * @return
     */
    public  Boolean resume(QuartzJob quartzJob) {
        Boolean result=true;
        try {
            JobKey key = new JobKey(quartzJob.getJobName(),quartzJob.getJobGroup());
            scheduler.resumeJob(key);
        } catch (SchedulerException e) {
            logger.error("恢复调度任务异常", e);
            result=false;
        }
        return result;
    }

    /**
     * 移除
     * @param quartzJob
     */
    public  Boolean remove(QuartzJob quartzJob) {
        Boolean result=true;
        try {

            TriggerKey triggerKey = TriggerKey.triggerKey(quartzJob.getJobName(), quartzJob.getJobGroup());
            if(triggerKey==null){
                logger.error("待移除的调度任务不存在");
                return false;
            }
            JobKey jobKey = JobKey.jobKey(quartzJob.getJobName(), quartzJob.getJobGroup());

            // 停止触发器
            scheduler.pauseTrigger(triggerKey);
            // 移除触发器
            scheduler.unscheduleJob(triggerKey);
            // 删除任务
            scheduler.deleteJob(jobKey);
        } catch (Exception e) {
            logger.error("移除调度任务异常", e);
            result=false;
        }
        return result;
    }

}
